import '@babel/polyfill';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import gsap from 'gsap';
import * as dat from 'dat.gui';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { Mesh } from 'three';

//场景
const scene = new THREE.Scene();

//相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 200);
camera.position.set(5, 3, 5);
scene.add(camera);

//渲染器
const renderer = new THREE.WebGL1Renderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//光
const ambientlight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientlight);
const directionLight = new THREE.DirectionalLight(0xffffff, 1);
directionLight.position.set(0, 0, 30);
scene.add(directionLight);

//plane
const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshStandardMaterial());
plane.position.set(0, 0, -3);
scene.add(plane);

//阴影
renderer.shadowMap.enabled = true;
plane.receiveShadow = true;
directionLight.castShadow = true;


const textureloader = new THREE.CubeTextureLoader();
textureloader.setPath('./textures/environmentMaps/0/');
const texture = textureloader.load([
    'px.jpg',
    'nx.jpg',
    'py.jpg',
    'ny.jpg',
    'pz.jpg',
    'nz.jpg',
]);
scene.background = texture;

const mapTexture = new THREE.TextureLoader().load('./models/LeePerrySmith/color.jpg');
const normalMapTexture = new THREE.TextureLoader().load('./models/LeePerrySmith/normal.jpg');

const material = new THREE.MeshStandardMaterial({
    map: mapTexture,
    normalMap: normalMapTexture,
});

const uniformsObj = { uTime: { value: 0 } };

material.onBeforeCompile = (shader) => {
    console.log(shader);
    console.log(shader.vertexShader)
    shader.uniforms.uTime = uniformsObj.uTime;
    //正则匹配
    shader.vertexShader = shader.vertexShader.replace(
        '#include <common>',//在最开始位置引入属性和定义的函数
        `
        #include <common>

        mat2 rotate2d(float _angle){
            return mat2(cos(_angle),-sin(_angle),
                        sin(_angle),cos(_angle));
        }
        uniform float uTime;
        `
    );
    shader.vertexShader = shader.vertexShader.replace(
        '#include <beginnormal_vertex>',//开始法向顶点
        //模型法向旋转修改
        `
        #include <beginnormal_vertex>

        float angle = position.y*0.3*sin(uTime);
        mat2 rotateMatrix = rotate2d(angle);

        objectNormal.xz = rotateMatrix * objectNormal.xz;
        `
    );
    shader.vertexShader = shader.vertexShader.replace(
        '#include <begin_vertex>',//开始顶点
        //xz变化，绕y轴旋转
        `
        #include <begin_vertex>

        transformed.xz = rotateMatrix * transformed.xz;
        `
    );
};

const depthMaterial = new THREE.MeshDepthMaterial({ depthPacking: THREE.RGBADepthPacking });
depthMaterial.onBeforeCompile = (shader) => {
    shader.uniforms.uTime = uniformsObj.uTime;
    shader.vertexShader = shader.vertexShader.replace(
        '#include <common>',//在最开始位置引入属性和定义的函数
        `
        #include <common>

        mat2 rotate2d(float _angle){
            return mat2(cos(_angle),-sin(_angle),
                        sin(_angle),cos(_angle));
        }
        uniform float uTime;
        `
    );
    shader.vertexShader = shader.vertexShader.replace(
        '#include <begin_vertex>',//开始顶点
        //xz变化，绕y轴旋转
        `
        #include <begin_vertex>

        float angle = position.y*0.3*sin(uTime);
        mat2 rotateMatrix = rotate2d(angle);

        transformed.xz = rotateMatrix * transformed.xz;
        `
    );
}



const gltfLoader = new GLTFLoader();
gltfLoader.load('./models/LeePerrySmith/LeePerrySmith.glb', (gltf) => {
    console.log(gltf);
    gltf.scene.children[0].material = material;
    //深度网格材质，阴影
    gltf.scene.children[0].customDepthMaterial = depthMaterial;
    scene.add(gltf.scene);
    gltf.scene.children[0].castShadow = true;

});


//控制
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.enableDamping = true;

const axes = new THREE.AxesHelper(5);
scene.add(axes);

const clock = new THREE.Clock();
//帧动画
function animate() {
    const time = clock.getElapsedTime();
    uniformsObj.uTime.value = time;
    orbitControls.update();
    renderer.render(scene, camera);
    requestAnimationFrame(animate);
};
animate();

//窗口调整侦听
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
});



